package com.scshyzh.concurrent;


import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;

/**
 * Manager of processors 处理器管理类<br>
 * Maintains the relationship between command and command processor through command code.
 *
 * @author songkui
 * @Author
 */
@Slf4j
public class MochaExecutorManager {

    private MochaExecutorPool executorPool;
    private MochaScheduler defaultScheduler;
    /**
     * The default executor, if no executor is set for processor, this one will be used 如果没有为处理类设置线程池,则默认此线程池
     */
    private ExecutorService defaultExecutor; 

    /**
     * minPoolSize(线程池的基本大小): 32
     * maxPoolSize(线程池最大大小): 512
     * queueSize(任务队列大小): 1024
     * keepAliveTime(线程活动保持时间): 60s
     */
    private int minPoolSize = ExecutorConfigManager.default_tp_min_size();

    private int minSchedulerPoolSize = ExecutorConfigManager.default_tsp_min_size();

    private int maxPoolSize = ExecutorConfigManager.default_tp_max_size();

    private int queueSize = ExecutorConfigManager.default_tp_queue_size();

    private long keepAliveTime = ExecutorConfigManager.default_tp_keepalive_time();

    private MochaExecutorManager() {
        defaultExecutor = MochaThreadPool.buildThreadPool(minPoolSize, maxPoolSize, queueSize, keepAliveTime, "mocha-pool");
        defaultScheduler = new MochaScheduler(minSchedulerPoolSize);
    }

    private static final class ProcessorManagerHolder {
        static final MochaExecutorManager processorManager = new MochaExecutorManager();
    }

    public static MochaExecutorManager getInstance() {
        return ProcessorManagerHolder.processorManager;
    }


    public void start(int size) {
        if (size == 0) {
            return;
        }
        int num = Runtime.getRuntime().availableProcessors() * size;
        num = num < 32 ? 32 : num;
        log.info("Initialize executorPool size {}", num);
        executorPool = new MochaExecutorPool(num, "mocha-dis");
        executorPool.start();
    }

    public MochaExecutor getDisruptorByUserId(long userId) {
        int index = (int) (userId % executorPool.size());
        return executorPool.getByIndex(index);
    }

    public MochaExecutor getDisruptor(int no) {
        return executorPool.getByBizNo(no);
    }


    public ExecutorService getDefaultExecutor() {
        return defaultExecutor;
    }

    public MochaScheduler getDefaultScheduler() {
        return defaultScheduler;
    }
}